package com.wl.lib.mvi

import android.R
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import androidx.viewbinding.ViewBinding
import java.lang.reflect.ParameterizedType


// Created by wangliang on 2024/4/25.
abstract class BaseBindingFragment<VB : ViewBinding> : BaseFragment() {

    // 子类使用的时候如果不能确定是否被释放，则需要使用此属性，避免出现空指针异常
    protected var _binding: VB? = null

    // 子类如果明确不会在 onDestroyView 后调用的话，可以使用此属性
    protected val binding: VB
        get() = requireNotNull(_binding) { "The property of binding has been destroyed." }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = initBinding(inflater)

        return binding.root
    }

    // 为了减少上层页面样板代码，采用反射形式来创建 binding，当然会损失一部分性能，先这样，如果有特殊需要可以覆盖此方法
    // Contributed by Xu Qiang
    @Suppress("UNCHECKED_CAST")
    protected fun initBinding(inflater: LayoutInflater): VB? {
        val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as? Class<*> ?: return null
        val method = type.getMethod("inflate", LayoutInflater::class.java)
        return method.invoke(null, inflater) as? VB
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    /**
     * 关闭Fragment
     */
    fun close() {
        val manager: FragmentManager = requireActivity().supportFragmentManager
        if (manager.backStackEntryCount > 0) {
            manager.popBackStack()
        } else {
            requireActivity().finish()
        }
    }

    fun show(activity: AppCompatActivity, fragment: Fragment, isAddStack: Boolean) {
        show(R.id.content, activity, fragment, isAddStack)
    }

    private fun show(
        containerID: Int,
        activity: AppCompatActivity,
        fragment: Fragment,
        isAddStack: Boolean
    ) {
        val manager = activity.supportFragmentManager
        val transaction = manager.beginTransaction()
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        if (isAddStack) {
            transaction.add(containerID, fragment).addToBackStack(fragment.javaClass.name)
                .commitAllowingStateLoss()
        } else {
            transaction.add(containerID, fragment).commitAllowingStateLoss()
        }
    }
}